import { locations } from "../../../gpu/locations";
export const Animation = /*wgsl*/ `
#if ~{def.u_MorphTargetsSampler}
@group(${locations.u_MorphTargetsSampler[0]}) @binding(${locations.u_MorphTargetsSampler[1]}) var u_MorphTargetsSampler :texture_2d_array<f32>;
#endif 
#if ~{def.u_morphWeights}
// @group(${locations.u_morphWeights[0]}) @binding(${locations.u_morphWeights[1]}) var<uniform> u_morphWeights : vec~{def.WEIGHT_COUNT}<f32>;
@group(${locations.u_morphWeights[0]}) @binding(${locations.u_morphWeights[1]}) var<storage, read> u_morphWeights : array<f32>;
#endif
#if ~{def.jointMatrixs}
@group(${locations.jointMatrixs[0]}) @binding(${locations.jointMatrixs[1]}) var jointMatrixs : texture_2d<f32>;
#endif 
fn create_identity_matrix() -> mat4x4<f32> {  
    return mat4x4<f32>(  
        vec4(1.0, 0.0, 0.0, 0.0),  
        vec4(0.0, 1.0, 0.0, 0.0),  
        vec4(0.0, 0.0, 1.0, 0.0),  
        vec4(0.0, 0.0, 0.0, 1.0)  
    );  
}
// 计算 4x4 矩阵的逆并返回其转置  
fn inverse_transpose_4x4(mat: mat4x4<f32>) -> mat4x4<f32> {  
    // 计算行列式  
    let a = mat[0][0];let b = mat[0][1];let c = mat[0][2];let d = mat[0][3];  
    let e = mat[1][0];let f = mat[1][1];let g = mat[1][2];let h = mat[1][3];  
    let i = mat[2][0];let j = mat[2][1];let k = mat[2][2];let l = mat[2][3];  
    let m = mat[3][0];let n = mat[3][1];let o = mat[3][2];let p = mat[3][3];  

    let det = a * (f * (k * p - l * o) - g * (j * p - l * n) + h * (j * o - k * n))   
                - b * (e * (k * p - l * o) - g * (i * p - l * m) + h * (i * o - k * m))   
                + c * (e * (j * p - l * n) - f * (i * p - l * m) + h * (i * n - j * m))   
                - d * (e * (j * o - k * n) - f * (i * o - k * m) + g * (i * n - j * m));  

    // 确定行列式是否为零  
    if (det == 0.0) {  
        // 处理不可逆矩阵的情况  
        return mat4x4<f32>(0.0, 0.0, 0.0, 0.0,  
                         0.0, 0.0, 0.0, 0.0,  
                         0.0, 0.0, 0.0, 0.0,  
                         0.0, 0.0, 0.0, 0.0); // 简单返回零矩阵  
    }  
    // 计算逆矩阵（使用伴随法则），此处应计算每个子矩阵的行列式并构造伴随矩阵  
    let inv_mat = (1.0 / det) * mat4x4<f32>(  
        f * (k * p - l * o) - g * (j * p - l * n) + h * (j * o - k * n),  
        -(b * (k * p - l * o) - c * (j * p - l * n) + d * (j * o - k * n)),  
        e * (g * p - h * o) - f * (g * n - h * m) + i * (g * o - h * m),  
        -(b * (g * p - h * o) - c * (g * n - h * m) + d * (g * o - h * m)),  
        
        -(e * (k * p - l * o) - g * (j * p - l * n) + h * (j * o - k * n)),  
        a * (k * p - l * o) - c * (j * p - l * n) + d * (j * o - k * n),  
        -(e * (g * p - h * o) - f * (g * n - h * m) + i * (g * o - h * m)),  
        a * (g * p - h * o) - b * (g * n - h * m) + d * (g * o - h * m),  
        
        e * (j * p - l * n) - f * (j * o - k * n) + h * (i * n - j * m),  
        -(a * (j * p - l * n) - b * (j * o - k * n) + d * (i * n - j * m)),  
        -(e * (i * p - l * m) - f * (i * o - k * m) + h * (i * n - j * m)),  
        a * (i * p - l * m) - b * (i * o - k * m) + c * (i * n - j * m),  
        
        -(e * (j * o - k * n) - f * (j * n - i * n) + g * (i * n - j * m)),  
        a * (j * o - k * n) - b * (j * n - i * n) + c * (i * n - j * m),  
        a * (i * o - k * m) - b * (i * n - j * m) + c * (j * n - i * n),  
        a * (i * o - l * m) - b * (i * n - j * m) + c * (j * n - i * n)  
    );  

    // 返回逆矩阵的转置  
    return transpose(inv_mat);  
}  

fn is_zero_matrix(mat: mat4x4<f32>) -> bool {  
    return (mat[0][0] == 0.0 && mat[0][1] == 0.0 && mat[0][2] == 0.0 && mat[0][3] == 0.0) &&  
           (mat[1][0] == 0.0 && mat[1][1] == 0.0 && mat[1][2] == 0.0 && mat[1][3] == 0.0) &&  
           (mat[2][0] == 0.0 && mat[2][1] == 0.0 && mat[2][2] == 0.0 && mat[2][3] == 0.0) &&  
           (mat[3][0] == 0.0 && mat[3][1] == 0.0 && mat[3][2] == 0.0 && mat[3][3] == 0.0);  
} 
#if ~{def.jointMatrixs}
fn getMatrixFromTexture(index:u32)->mat4x4<f32>{
    var result:mat4x4<f32> =create_identity_matrix();
    var texSize:u32 = textureDimensions(jointMatrixs, 0)[0];
    var pixelIndex:u32 = index * 4;
    for (var i:u32 = 0; i < 4; i++){
        var x:u32 = (pixelIndex + i) % texSize;
        var y:u32 = (pixelIndex + i - x) / texSize; 
        result[i] = textureLoad(jointMatrixs, vec2<u32>(x,y), 0);
    }
    return result;
}
fn getSkinningMatrix(input:VertexInput)->mat4x4<f32>{
    var skin:mat4x4<f32> = mat4x4<f32>();
    #if ~{def.weights0&&def.joints0}
    skin +=
        input.weights0.x * getMatrixFromTexture(input.joints0.x) +
        input.weights0.y * getMatrixFromTexture(input.joints0.y) +
        input.weights0.z * getMatrixFromTexture(input.joints0.z) +
        input.weights0.w * getMatrixFromTexture(input.joints0.w);
    #endif
    #if ~{def.weight1&&def.joints1}
    skin +=
        input.weights1.x * getMatrixFromTexture(input.joints1.x) +
        input.weights1.y * getMatrixFromTexture(input.joints1.y) +
        input.weights1.z * getMatrixFromTexture(input.joints1.z) +
        input.weights1.w * getMatrixFromTexture(input.joints1.w);
    #endif
    if (is_zero_matrix(skin)) { 
        return create_identity_matrix(); 
    }
    return skin;
}


#endif 

#if ~{def.u_morphWeights}

#if ~{def.u_MorphTargetsSampler}
fn textureOffset( id:u32,  arrayIndex:u32,  size:u32)->vec4<f32>{
    var x:u32 = id % size;
    var y:u32 = (id - x) / size; 
    // var y:u32 = (vertexID - x) ; 
    return textureLoad(u_MorphTargetsSampler, vec2<u32>(x, y), arrayIndex,0);
}
#endif


fn morphPosition( id:u32)->vec4<f32>{
    var pos:vec4<f32> = vec4(0);
    var texSize:u32 = textureDimensions(u_MorphTargetsSampler, 0)[0];
    // 不要删除后面可能需要用
    // var depth:u32 = textureNumLayers(u_MorphTargetsSampler);
    for(var i:u32 = 0; i <~{def?.WEIGHT_COUNT}; i++){
      var offset:vec4<f32> = textureOffset(id, ~{def?.morphPositionOffset} + i, texSize);
      pos += u_morphWeights[i] * offset;
    }
    return pos;
}

fn morphNormal( id:u32)->vec3<f32>{
    var normal:vec3<f32> = vec3(0);
   #if ~{def.morphNormalOffset}
    var texSize:u32 = textureDimensions(u_MorphTargetsSampler, 0)[0];
    for(var i:u32 = 0; i < ~{def?.WEIGHT_COUNT}; i++){
      var offset:vec3<f32> = textureOffset(id, ~{def?.morphNormalOffset} + i, texSize).xyz;
        normal += u_morphWeights[i] * offset;
    }
#endif
    return normal;
}


fn morphTangent(id:u32)->vec3<f32>{
    var tangent:vec3<f32> = vec3(0);
   #if ~{def.morphTangentOffset}
    var texSize:u32 = textureDimensions(u_MorphTargetsSampler, 0)[0];
    for(var i:u32 = 0; i < ~{def?.WEIGHT_COUNT}; i++){
        var offset:vec3<f32> = textureOffset(id, ~{def?.morphTangentOffset} + i, texSize).xyz;
        tangent += u_morphWeights[i] * offset;
    }
#endif
    return tangent;
}

fn morphTexCoord0(id:u32)->vec2<f32>
{
     var uv:vec2<f32> = vec2(0);
    #if ~{def.morphTexcoordOffset}
    var texSize:u32 = textureDimensions(u_MorphTargetsSampler, 0)[0];
    for(var i:u32 = 0; i < ~{def?.WEIGHT_COUNT}; i++){
        var offset:vec2<f32> = textureOffset(id, ~{def?.morphTexcoordOffset} + i, texSize).xy;
        uv += u_morphWeights[i] * offset;
    }
    #endif
    return uv;
}

fn morphTexCoord1(id:u32)->vec2<f32>
{
    var uv:vec2<f32> = vec2(0);
    #if ~{def.morphTexcoord1Offset}
    var texSize:u32 = textureDimensions(u_MorphTargetsSampler, 0)[0];
    for(let i:u32 = 0; i < ~{def?.WEIGHT_COUNT}; i++){
      var offset:vec2<f32>  = textureOffset(id, ~{def?.morphTexcoord1Offset} + i, texSize).xy;
        uv += u_morphWeights[i] * offset;
    }
#endif
    return uv;
}

fn morphColor0(id:u32)->vec4<f32>
{
    var color:vec4<f32> = vec4(0);
    #if ~{def.morphColor0Offset}
    var texSize:u32 = textureDimensions(u_MorphTargetsSampler, 0)[0];
    for(let i:u32 = 0; i < ~{def?.WEIGHT_COUNT}; i++){
        var offset:vec4<f32> = textureOffset(id, ~{def?.morphColor0Offset} + i, texSize);
        color += u_morphWeights[i] * offset;
    }
#endif
    return color;
}
#endif 
`;
